<template>
  <div clas="video-upload">
    <el-upload
      class="upload-demo"
      ref="mediaUpload"
      drag
      action=""
      :on-change="handleChange"
      :file-list="fileList"
      :show-file-list="false"
      :auto-upload="false"
      accept="video/mp4,video/x-m4v,video/*,.mkv,.rmvb"
      multiple
      v-permission="['course:save']"
    >
      <div>
        <p>上传视频最大不能超过5G</p>
        <p>支持的格式：MP4、TS、FLV、WMV、ASF、RM、RMVB、MPG、MPEG、3GP、MOV、WEBM、MKV、AVI</p>
        <p>不得上传未经他人授权的作品，以及色情、反动等违法视频</p>
      </div>
    </el-upload>

    <!-- 等待上传的队列 -->
    <div class="current-video">
      <draggable class="video-list" v-model="fileList" handle=".drag-btn">
        <video-preview
          ref="videoPreviewWait"
          :is-video="true"
          v-for="(video, index) in fileList"
          v-model="fileList[index]"
          @remove="removeFile(index)"
          :key="video.uid"
          :can-drag="uploadedCount == fileList.length"
        ></video-preview>
      </draggable>
      <div class="current-video-btn" sticky-container v-if="fileList.length > 0">
        <div v-sticky sticky-offset="{ top: 10 }">
          <el-button
            type="primary"
            icon="el-icon-upload"
            @click="uploadAll"
            :disabled="!hasWaitUploadImage"
          >
            上传视频
          </el-button>
          <el-button
            type="success"
            :loading="saveLoading"
            icon="el-icon-check"
            @click="saveAllVideoInfo"
          >
            保存信息
          </el-button>
          <p class="tips">
            <span v-if="fileList.length > 0">
              视频上传成功之后,记得点上边⬆️的"保存信息"按钮!
            </span>
          </p>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
  // 部分复制了 /Media/Upload
  import VideoPreview from 'comp/VideoPreview';
  import Sticky from 'vue-sticky-directive';

  export default {
    directives: {
      sticky: Sticky,
    },
    data() {
      return {
        fileList: [],
        uploaderList: [],
        uploadedCount: 0,
        saveLoading: false,
      };
    },
    components: {
      VideoPreview,
    },
    computed: {
      hasWaitUploadImage() {
        return !!this.fileList.filter((file) => file.status === 'ready');
      },
    },
    methods: {
      /**
       * 移除上传队列中的文件
       */
      removeFile(index) {
        this.$confirm(`确认从上传队列中删除 ${this.fileList[index].name} 吗?`).then(() => {
          this.abortUpload(index);
          this.fileList.splice(index, 1);
          this.uploadedCount -= 1;

          if (this.uploaderList[index]) {
            // 删除上传文件
            this.uploaderList[index].deleteFile(0);
            // 清空上传对象
            this.uploaderList[index] = null;
            // 删除上传对象
            this.uploaderList.splice(index, 1);
          }
        });
      },
      /**
       * 取消一个文件上传
       * Doc: https://help.aliyun.com/document_detail/52204.html
       */
      abortUpload(index) {
        const file = this.fileList[index].raw;
        this.$refs.mediaUpload.abort(file);
        // 这里是索引始终都是第0个
        if (this.uploaderList[index]) {
          this.uploaderList[index].cancelFile(0);
          this.$set(this.fileList[index], 'status', 'abort');
        }
      },
      /**
       * 文件列表
       */
      handleChange(file, fileList) {
        this.fileList = [...fileList];
      },
      /**
       * 检查所有的数据啦
       */
      saveAllVideoInfo() {
        if (this.saveLoading) return;
        this.saveLoading = true;

        Promise.all(this.$refs.videoPreviewWait.map((vpc) => vpc.valid()))
          .then((res) => {
            this.$service
              .AssetVideoSave(
                {
                  videos: this.fileList,
                },
                {
                  ...JSON_HEADER,
                },
              )
              .then(() => {
                this.fileList = [];
                this.$message.success('新增视频成功!请去视频列表中查找相关视频');
              });
          })
          .catch((err) => {
            console.log(err);
            this.$message.error('有必填项未填写');
          })
          .finally(() => {
            this.saveLoading = false;
          });
      },
      /**
       * 上传所有视频
       */
      uploadAll() {
        // if (this.uploadStart) return;
        // this.uploadStart = true;

        this.$notify({
          message: '开始上传啰!~~~~',
          type: 'success',
        });

        this.fileList.forEach(async (file, index) => {
          try {
            if (file.status === 'ready') {
              await this.uploadSingleVideo(index);
            }
          } catch (e) {
            console.log(e);
          }
        });
      },
      /**
       * 上传单个视频
       */
      async uploadSingleVideo(index) {
        const file = this.fileList[index];

        const uploader = new AliyunUpload.Vod({
          userId: process.env.VUE_APP_ALIYUN_ACCOUNT, //阿里账号ID，必须有值
          // partSize: 1048576, //分片大小默认1M，不能小于100K
          // parallel: 5,  //并行上传分片个数，默认5
          // retryCount: 3, //网络原因失败时，重新上传次数，默认为3
          // retryDuration: 2, //网络原因失败时，重新上传间隔时间，默认为2秒
          // enableUploadProgress: true, //是否上报上传日志到点播，默认为true
          // 开始上传
          onUploadstarted: async (uploadInfo) => {
            if (!this.fileList[index]) return;

            this.$set(this.fileList[index], 'status', 'uploading');

            if (uploadInfo.videoId) {
              const { uploadAuth } = await this.$service.AssetUploadRefresh({
                vid: uploadInfo.videoId,
              });
              uploader.resumeUploadWithAuth(uploadAuth);
            } else {
              //从点播服务获取的uploadAuth、uploadAddress和videoId,设置到SDK里
              const { uploadAuth, uploadAddress, videoId } = await this.$service.AssetUploadFetch({
                filename: file.name,
              });
              //获取
              uploader.setUploadAuthAndAddress(uploadInfo, uploadAuth, uploadAddress, videoId);
            }
          },
          // 文件上传成功
          onUploadSucceed: (uploadInfo) => {
            if (!this.fileList[index]) return;

            this.$message.success(`${file.name} 上传成功`);
            this.$set(this.fileList[index], 'status', 'done');
            this.$set(this.fileList[index], 'showVideoId', uploadInfo.videoId);
            this.uploadedCount += 1;
          },
          // 文件上传失败
          onUploadFailed: (uploadInfo, code, message) => {
            this.$message.error(`${file.name}上传失败! Code:${code}, 错误信息:${message}`);
          },
          // 文件上传进度，单位：字节
          onUploadProgress: (uploadInfo, totalSize, loadedPercent) => {
            if (!this.fileList[index]) return;

            const percentage = Math.ceil(loadedPercent * 100);
            this.$set(this.fileList[index], 'percentage', percentage);
          },
          onUploadCanceled() {},
          // 上传凭证超时
          onUploadTokenExpired: async (uploadInfo) => {
            //实现时，根据uploadInfo.videoId调用刷新视频上传凭证接口重新获取UploadAuth
            //https://help.aliyun.com/document_detail/55408.html
            //从点播服务刷新的uploadAuth,设置到SDK里
            const { uploadAuth } = await this.$service.AssetUploadRefresh({
              vid: uploadInfo.videoId,
            });
            uploader.resumeUploadWithAuth(uploadAuth);
          },
        });

        const userData = '{"Vod": {}}';
        uploader.addFile(file.raw, null, null, null, userData);
        uploader.startUpload();
        // uploader和fileList对应起来
        this.uploaderList[index] = uploader;
      },
    },
  };
</script>

<style lang="less" scoped>
  .upload-demo {
    height: 100px;
    width: 100%;
    margin-bottom: 20px;
  }

  .current-video {
    display: flex;
    counter-reset: order;

    .video-list {
      flex: 1;
    }

    &-btn {
      width: 130px;
      padding: 0 10px;

      /deep/ .el-button {
        margin-bottom: 10px;
        margin-left: 0;
      }
    }
  }
</style>
<style lang="less">
  .el-upload {
    display: block;
    height: 100%;
    .el-upload-dragger {
      width: 100%;
      height: 100%;
      display: flex;
      justify-content: center;
      align-items: center;
      color: #aaa;
    }
  }

  .btn-box {
    margin-top: 10px;
  }
</style>
